﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Server
{
    public partial class FrmSever : Form
    {
        /// <summary>
        /// 构造函数 初始化答题器
        /// </summary>
        public FrmSever()
        {
            InitializeComponent();
            //执行ICO
            this.Icon = Properties.Resources.app;
            LapIcon.Icon = Properties.Resources.app;
            //事件委托创建
            msgShowEvent = ListBoxMsgShow;
            //服务器订阅答题服务的事件
            DatiSeverModel.AnswerCheck += GetAnswer;
            DatiSeverModel.ReicveQuestionImage += ReicveQuestionImage;
            btnQuery_Click(null, null);
            //开启工作线程
            new Task(DatiWorker).Start();
        }

        /// <summary>
        /// 启动答题服务
        /// </summary>
        private void StartSever()
        {
            //答题服务器Chanel初始化和注册
            var serverChanel = new TcpServerChannel(13140);
            ChannelServices.RegisterChannel(serverChanel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(DatiSeverModel), "Dati", WellKnownObjectMode.Singleton);
            MsgShow("服务器启动……");
        }

        /// <summary>
        /// 非UI线程要求UI显示数据
        /// </summary>
        /// <param name="sender"></param>
        private void MsgShow(object sender)
        {
            Invoke(msgShowEvent, sender as string);
        }

        /// <summary>
        /// 委托定义
        /// </summary>
        /// <param name="msg"></param>
        private delegate void MsgShowHandler(string msg);

        /// <summary>
        /// 非UI展示数据委托事件
        /// </summary>
        private readonly MsgShowHandler msgShowEvent;

        /// <summary>
        /// UI线程直接展示数据
        /// </summary>
        /// <param name="msg"></param>
        private void ListBoxMsgShow(string msg)
        {
            listBox1.Items.Add(string.Format("{0} {1}", DateTime.Now, msg));
            listBox1.TopIndex = listBox1.Items.Count - 7;
            Text = string.Format("答题服务器  剩余题目：{0}", questions.Count);
        }

        /// <summary>
        /// 从集合中查询答案
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private int GetAnswer(int id)
        {
            return answer.FirstOrDefault(ques => ques.Key == id).Value;
        }

        /// <summary>
        /// 接受答题图片构建出问题并且加入答题队列
        /// </summary>
        /// <param name="id"></param>
        /// <param name="imageBuffer"></param>
        private void ReicveQuestionImage(int id, byte[] imageBuffer)
        {
            //1.接收数据建立对象
            var ms = new MemoryStream(imageBuffer);
            var ques = new Question { Id = id, QuestionImage = Image.FromStream(ms), RecvTime = DateTime.Now };
            if (ques.QuestionImage != null)
            {
                //保证数据写入的唯一
                lock (questions)
                {
                    questions.Enqueue(ques);
                    wait.Set();
                }
                MsgShow(string.Format("题目{0:000}->接受问题图片", id));
            }
            ms.Close();
        }


        /// <summary>
        /// 获取问题
        /// </summary>
        /// <param name="question">返回队列中的问题对象</param>
        /// <param name="overTime"></param>
        /// <returns>返回是否取到了问题</returns>
        private bool CheckQuestionQueue(ref Question question, ref DateTime overTime)
        {
            if (questions.Count > 0)
            {
                question = questions.Dequeue();
                overTime = question.RecvTime.AddSeconds(40);
                return true;
            }
            wait.Reset();
            return false;
        }

        /// <summary>
        /// 问题队列
        /// </summary>
        private readonly Queue<Question> questions = new Queue<Question>();

        /// <summary>
        /// 答案缓存
        /// </summary>
        private readonly Dictionary<int, int> answer = new Dictionary<int, int>();

        /// <summary>
        /// 标记是否正在回答问题
        /// </summary>
        private bool answering;

        /// <summary>
        /// 当前正在回答的问题的信息
        /// </summary>
        private Question theAnsweringQuestion;

        private readonly ManualResetEvent wait = new ManualResetEvent(true);

        /// <summary>
        /// 答题工作线程
        /// </summary>
        private void DatiWorker()
        {
            StartSever();
            DateTime overTime = DateTime.Now;
            while (!serverStop)
            {
                if (answering)
                {
                    if (DateTime.Now < overTime)
                    {
                        Thread.Sleep(500);//继续检查
                        Console.Beep();
                    }
                    else
                    {
                        temAnswer = new Random().Next(0, 9999999) % 4 + 1;
                        this.Invoke((MethodInvoker)(() => SetAnswer(temAnswer)));
                        MsgShow("超时答题随机设置为" + temAnswer);
                    }
                }
                else if (CheckQuestionQueue(ref theAnsweringQuestion, ref overTime))
                {
                    ShowQuestionImage();
                }
                else
                {
                    wait.WaitOne();
                }
            }
        }


        /// <summary>
        /// 展示图片
        /// </summary>
        private void ShowQuestionImage()
        {
            temAnswer = 0;
            answering = true;
            RadioButtonsEnable(true);
        }

        /// <summary>
        /// 设置答案
        /// </summary>
        /// <param name="an"></param>
        private void SetAnswer(int an)
        {
            if (theAnsweringQuestion != null)
            {
                //缓存答案
                if (temAnswer != an)
                {
                    temAnswer = an;
                }
                else
                {
                    //对答案进行二次确认
                    answer.Add(theAnsweringQuestion.Id, an);
                    ListBoxMsgShow(string.Format("题目{0:000}->设置答案为:{1}", theAnsweringQuestion.Id, an));
                    QuestionImage.Image = null;
                    theAnsweringQuestion.Dispose();
                    theAnsweringQuestion = null;
                    TopMost = false;
                    RadioButtonsEnable(false);
                    answering = false;
                }
            }
        }

        /// <summary>
        /// 答题按钮展示
        /// </summary>
        /// <param name="show"></param>
        private void RadioButtonsEnable(bool show)
        {
            Invoke((MethodInvoker)delegate
            {
                if (show)
                {
                    Show();
                    WindowState = FormWindowState.Normal;
                    TopMost = true;
                    QuestionImage.Image = theAnsweringQuestion.QuestionImage;
                }
                lbAn1.Visible = lbAn2.Visible = lbAn3.Visible = lbAn4.Visible = show;
            });
        }

        /// <summary>
        /// 缓存答案
        /// </summary>
        private int temAnswer = 0;

        /// <summary>
        /// 鼠标单击答题控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LbAnClick(object sender, EventArgs e)
        {
            var control = sender as Control;
            if (control != null)
            {
                SetAnswer(int.Parse(control.Text.Trim()));
            }
        }

        /// <summary>
        /// 鼠标双击答题标签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LbAnDoubleClick(object sender, EventArgs e)
        {
            var label = sender as Label;
            if (label != null)
            {
                temAnswer = int.Parse(label.Text.Trim());
                SetAnswer(temAnswer);
            }
        }


        #region 服务器UI变化
        /// <summary>
        /// 控制APP关闭
        /// </summary>
        private bool serverStop = false;
        /// <summary>
        /// APP退出结束
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ApplicationExit(object sender, EventArgs e)
        {
            serverStop = true;
            Application.Exit();
        }
        /// <summary>
        /// APP关闭按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmSever_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!serverStop)
            {
                e.Cancel = true;
                this.Hide();
            }
        }

        /// <summary>
        /// 鼠标移动到标签上
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LbAnMouseEnter(object sender, EventArgs e)
        {
            var label = sender as Label;
            if (label != null)
            {
                label.ForeColor = Color.Red;
                label.BackColor = Color.Yellow;
            }
        }

        /// <summary>
        /// 鼠标移出标签范围
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LbAnMouseLeave(object sender, EventArgs e)
        {
            var label = sender as Label;
            if (label != null)
            {
                label.BackColor = Color.Black;
                label.ForeColor = Color.White;
            }
        }

        /// <summary>
        /// 小图标双击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LapIcon_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }
        #endregion

        /// <summary>
        /// 主机信息查询
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnQuery_Click(object sender, EventArgs e)
        {
            //查询指定计算机的IP
            cmbSeverIp.Items.Clear();
            cmbSeverIp.Items.Add(Dns.GetHostName());
            var ipList = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (var ip in ipList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    cmbSeverIp.Items.Add(ip);
                }
            }
            if (cmbSeverIp.Items.Count > 0)
                cmbSeverIp.Text = cmbSeverIp.Items[0].ToString();
        }
    }

}




